
/**
 * @File    xxx
 * @brief   xxx
 * @auhtor  xxx
 * @data    xxx
 * @see     xxx
 * @note    xxx
**/

#include "server.h"

#ifndef h_addr
#define h_addr h_addr_list[0]
#endif // h_addr

// 创建监听端口.
int create_listen(char *addr, short port)
{
    struct sockaddr_in sin;
    int sockfd;

    memset (&sin, '\0', sizeof (sin));

    if(addr != NULL)
    {
        struct in_addr val;
        if(inet_aton(addr, &val) != 0)
        {
            sin.sin_addr.s_addr = val.s_addr;
        }
        else
        {
            struct  hostent *ht;
            ht = gethostbyname(addr);
            if(ht == NULL)
            {
                perror ("gethostbyname() error");
                return -1;
            }
            memcpy(&sin.sin_addr.s_addr, ht->h_addr, ht->h_length);
        }
    }
    else
    {
        sin.sin_addr.s_addr = INADDR_ANY;
    }

    sin.sin_port = htons (port);
    sin.sin_family = AF_INET;

    sockfd = socket (PF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        perror ("socket() error");
        return -1;
    }

    int i=1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
    //i=1;
    //setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &i, sizeof(i));

    if (bind (sockfd, (struct sockaddr *) &sin, sizeof (sin)) == -1)
    {
        perror ("bind() error");
        return -1;
    }
    if (listen (sockfd, LISTEN_MAX) == -1)
    {
        perror ("listen() error");
        return -1;
    }

    set_noblock(sockfd);

    return sockfd;
}

// 接收客户端的连接.
int accept_connect(int sockfd)
{
    struct sockaddr sa;
    socklen_t a;
    int conn;

    conn = accept(sockfd, &sa, &a);
    if(conn == -1)
    {
        //	perror("accept() error");
    }

    set_noblock(conn);

    return conn;
}

// 创建一个连接.
int create_connect(char *addr, short port)
{
    struct sockaddr_in sin;
    int sockfd;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset (&sin, '\0', sizeof (sin));

    if(addr != NULL)
    {
        struct in_addr val;
        if(inet_aton(addr, &val) != 0)
        {
            sin.sin_addr.s_addr = val.s_addr;
        }
        else
        {
            struct  hostent *ht;
            ht = gethostbyname(addr);
            if(ht == NULL)
            {
                perror ("gethostbyname() error");
                return -1;
            }
            memcpy(&sin.sin_addr.s_addr, ht->h_addr, ht->h_length);
        }
    }
    else
    {
        sin.sin_addr.s_addr = INADDR_ANY;
    }

    sin.sin_port = htons (port);
    sin.sin_family = AF_INET;

    if(connect(sockfd, (struct sockaddr *)&sin, sizeof(struct sockaddr)) != 0)
    {
        perror ("connect() error");
        return -1;
    }

    set_noblock(sockfd);

    return sockfd;
}

int set_noblock(int fd)
{
    int flag;

    flag = fcntl(fd,F_GETFL);

    return fcntl(fd, F_SETFL, flag|O_NONBLOCK);
}

// 创建数据报端口.
int create_datagram(char *addr, short port)
{
    struct sockaddr_in sin;
    int sockfd;

    memset (&sin, '\0', sizeof (sin));

    if(addr != NULL)
    {
        struct in_addr val;
        if(inet_aton(addr, &val) != 0)
        {
            sin.sin_addr.s_addr = val.s_addr;
        }
        else
        {
            struct  hostent *ht;
            ht = gethostbyname(addr);
            if(ht == NULL)
            {
                perror ("gethostbyname() error");
                return -1;
            }
            memcpy(&sin.sin_addr.s_addr, ht->h_addr, ht->h_length);
        }
    }
    else
    {
        sin.sin_addr.s_addr = INADDR_ANY;
    }

    sin.sin_port = htons (port);
    sin.sin_family = AF_INET;

    sockfd = socket (PF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror ("socket() error");
        return -1;
    }

    int i=1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));

    if (bind (sockfd, (struct sockaddr *) &sin, sizeof (sin)) == -1)
    {
        perror ("bind() error");
        return -1;
    }

    set_noblock(sockfd);

    return sockfd;
}

// 设置SOCKET缓冲区大小.
int set_socket_buf(int fd, int rbuf_num, int sbuf_num)
{
    // 接收缓冲区.
    if(recv >= 0)
    {
        int nRecvBuf=rbuf_num;
        setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
    }
    // 发送缓冲区.
    if(send>= 0)
    {
        int nSendBuf=sbuf_num;
        setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));
    }

    return 0;
}

